package com.interview.b_并发.d_单例模式.a_双重锁检查;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class Test {
    static CyclicBarrier cyclicBarrier = new CyclicBarrier(100000);

    public static void main(String[] args) {

        for (int i = 0; i < 100000; i++) {
            new Thread(() -> {
                try {
                    System.out.println(cyclicBarrier.getNumberWaiting());
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
                SingleCheck instance = SingleCheck.getInstance();
                if (instance == null) {
                    System.err.println("null.................................");
                } else {

                    if (instance.a != 1 || instance.b != 2 || instance.c != 3) {
                        System.err.println("异常.................................");
                    } else {
                        System.err.println(instance.a + "  " + instance.b + "  " + instance.c + "");

                    }
                }

            }).start();
        }


    }


}


class SingleCheck {

    int a = 0;
    int b = 0;
    int c = 0;

    /**
     * 此处 volatile 是为了禁止重排序
     * 导致 创建对象实例时 ， 突然线程切换
     * 正常顺序（1.给变量分配内存 2.执行构造函数 3.指向内存地址）
     * <p>
     * 因为重排序的原因 导致分配内存 + 指向内存地址 完成，但是 构造函数没执行！
     * <p>
     * 此时 另一个线程过来，因为 synchronized具备可见性
     * 第一层检查就看到，对象不为空，但是对象的构造函数并没执行完毕，属于残缺的对象，必然会出现问题
     */
    private static volatile SingleCheck singleCheck;

    private SingleCheck() {
        a = 1;
        b = 2;
        c = 3;
    }

    /**
     * 此处双重检查加锁
     * 是为了解决并发 +节约资源
     */
    static SingleCheck getInstance() {
        if (singleCheck == null) {
            synchronized (SingleCheck.class) {
                if (singleCheck == null) {
                    singleCheck = new SingleCheck();
                }
            }
        }
        return singleCheck;
    }


}
